#include "WorldSocket.hpp"
#include "MessageBuffer.hpp"
#include "Socket.hpp"
#include "WorldPacket.hpp"
#include <cassert>
#include <cstdint>
#include <memory>
#include <mutex>

WorldSocket::WorldSocket(boost::asio::ip::tcp::socket&& sc) : Socket{std::move(sc)}
{
  _headerMessage.Resize(sizeof(HeaderPacket));
}

bool WorldSocket::Update()
{
  while(!_writePacketQueue.empty())
  {
    std::shared_ptr<WorldPacket> packet = _writePacketQueue.pop();
    HeaderPacket header = {packet->ReadSize(), packet->GetOpcode()};
    MessageBuffer msg(packet->ReadSize() + sizeof(HeaderPacket));
    
    msg.Write((void*)&header, sizeof(HeaderPacket));
    msg.WriteCompleted(sizeof(HeaderPacket));
    
    msg.Write(packet->ReadBegin(), packet->ReadSize());
    msg.WriteCompleted(packet->ReadSize());

    WriteMessage(std::move(msg));
  }
  return Socket<WorldSocket>::Update();
}

bool WorldSocket::HandleRead()
{
#if 0
    MessageBuffer& msg = GetReadBuffer();
    if(msg.GetActiveSize() > 0)
    {
      std::string str((const char*)msg.GetReadPointer(), msg.GetActiveSize());
      std::cout << "revice msg: " << str << std::endl;
    }
    msg.ReadCompleted(msg.GetActiveSize());
    return true;
#else

    MessageBuffer& msg = GetReadBuffer();
    while(msg.GetActiveSize() > 0)
    {
      // 还剩下空间，说明包头还没完整
      if(_headerMessage.GetRemainingSpace() > 0)
      {
        uint16_t recvSize = std::min(_headerMessage.GetRemainingSpace(), msg.GetActiveSize());
        _headerMessage.Write(msg.GetReadPointer(), recvSize);
        _headerMessage.WriteCompleted(recvSize);
        msg.ReadCompleted(recvSize);

        if(_headerMessage.GetRemainingSpace() > 0)
        {
          // 理论断言不可能生效
          assert(msg.GetActiveSize() == 0);
          break;
        }

        // 包头完整，初始化包头大小
        HeaderPacket* header = (HeaderPacket*)_headerMessage.GetReadPointer();
        if(!header->IsVaildSize())
        {
          return false;
        }
        _dataMessage.Resize(header->_size);
      }

      if(msg.GetActiveSize() > 0)
      {
        if(_dataMessage.GetRemainingSpace() > 0)
        {
          // 接收包体
          uint32_t recvSize = std::min(_dataMessage.GetRemainingSpace(), msg.GetActiveSize());
          _dataMessage.Write(msg.GetReadPointer(), recvSize);
          _dataMessage.WriteCompleted(recvSize);
          msg.ReadCompleted(recvSize);

          if(_dataMessage.GetRemainingSpace() > 0)
          {
            assert(msg.GetActiveSize() == 0);
            break;
          }

          // 包体完整，打包放到队列
          HeaderPacket* header = (HeaderPacket*)_headerMessage.GetReadPointer();
          std::shared_ptr<WorldPacket> packet = std::make_shared<WorldPacket>(header->_opcode, header->_size);
          packet->Append(_dataMessage.GetReadPointer(), header->_size);
          AddRecvPacket(std::move(packet));

          // 清空
          _dataMessage.Reset();
          _headerMessage.Reset();
        }
      }

      // 继续处理下一个
    }
  return true;    
#endif
}

void WorldSocket::SendPacket(WorldPacket&& packet)
{
  _writePacketQueue.push(std::make_shared<WorldPacket>(std::move(packet)));
}

void WorldSocket::AddRecvPacket(std::shared_ptr<WorldPacket>&& packet)
{
  _recvPacketQueue.push(std::move(packet));
}